#pragma once

#include<iostream>
#include<string>
#include<pthread.h>
#include<functional>
#include<stdio.h>
#include<assert.h>

using namespace std;

typedef function<void *(void*)> func_t;
const int num = 64;

class Thread
{
private:
    static void* start_routine(void* args)
    {
        Thread* _this = static_cast<Thread*>(args);
        return _this->callback();
    }
public:
    Thread()
    {
        char buffer[num];
        snprintf(buffer,sizeof(buffer),"thread->%d",_threadnum++);
        _name = buffer;
    }

    void start(func_t func,void *args = nullptr)
    {
        _func = func;
        _args = args;
        int n = pthread_create(&_tid,nullptr,start_routine,this);
        assert(n==0);
        (void)n;
    }

    void join()
    {
        int n = pthread_join(_tid,nullptr);
        assert(n==0);
        (void)n;
    }

    string getName(){return _name;}

    ~Thread(){}

    void* callback(){return _func(_args);}

private:
    string _name;
    func_t _func;
    void* _args;
    pthread_t _tid;
    static int _threadnum;
};

int Thread::_threadnum = 1;
